Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
Mac and OpenDoc are trademarks of Apple Computer, Inc.
Alerts and Modal Dialogs
In the case of alerts and modal dialogs, it is not necessary to create an ODWindow. The Macintosh Toolbox routines Alert() and ModalDialog() take an event filter routine as a parameter, so an ODWindow is not required to get events back to the part. The part should still request the modal focus for one of its frames, and in this case the frame which displayed the dialog is the most approriate choice. Alternatively, the part could create the dialog window, register it with the window state, and request the modal focus for the root frame of the window.
If a dialog event filter is used, it can call the Dispatcher to handle null events, update events and activate events for other windows, but should not call it for other events, because you wouldn't want a part embedded in the window behind the dialog to get mouse clicks, for example.
New in DR2: The utility files DlogUtil.h and DlogUtil.cpp contain a fairly robust routine for loading dialogs (ODGetNewDialog) and an accompanying filter proc which supports pseudo-moveable modals.
New in DR3: See the recipe Shared Utility Windows
As a consequence of OpenDoc's implementation of floating windows, part editors must call ODWindowState::DeactivateFrontWindows() before displaying a modal dialog, and ODWindowState::ActivateFrontWindows() after dismissing it. These methods operate on all floating windows and the frontmost non-floating window.
The following method of the Clock part displays the “About Box”.
In this case, the part could relinquish the modal focus instead of transferring it back to its previous owner, but by saving and restoring the owner of the modal focus, this recipe should work for nested modal dialogs, if a dialog was itself built from parts.
Note: The Clock Part uses a PICT for its about box. It calls ModalDialog() in a loop, and dismisses the dialog on mouse up so that there isn't a lingering mouse up to erroneously activate a part once the dialog is dismissed.
New in DR3: The dispatcher caches the facet that receives a mouse down, and mouse up events generally go to the same facet, so it’s important not to dismiss dialogs on mouse down because this would invalidate the facet cached by the dispatcher.
Dialog Filter
The dialog filter can call the Dispatcher to handle null events, update events and activate events for other windows.
else if ((event->what == keyDown) || (event->what == autoKey))
{
handled = kODTrue;
*itemHit = 1;
}
return handled;
}
The part editor will need access to the session. Using a global is fine, but the the refCon of the window could be used instead.
Relinquishing the Modal Focus
Parts will generally be unwilling to relinquish the modal focus. In Part::BeginRelinquishFocus:
if (focus == fModalFocus))
return kODFalse;
Movable Modal Dialogs
A movable modal dialog which strictly follows the Macintosh Human Interface guidelines allows the user to switch out to other processes. To implement such a dialog, ModalDialog() can not be used, and an ODWindow must be creates as shown below.
New in DR2: The filter proc in DlogUtil.cpp can be used with ModalDialog() and modal dialogs which can move but do not allow switching out to other processes. Many reasonable people consider this quite adequate, and certainly preferable to a modal dialog which can’t move at all.
Displaying the Dialog
The following method of the Clock part displays the Synchronize… dialog, which is a true movable modal.
// ODReleaseObject(ev, window); // released by CloseAndRemove
clockPart->GetMenuBar()->EnableAll(ev);
InvalMenuBar();
}
else
ODReleaseObject(ev, window);
}
return wasHandled;
}
Note: The dialog is only dismissed on mouse up, because of the call to DialogSelect().
Modeless Dialogs
Showing the dialog
Suppose the user chooses a menu item to show a modeless dialog. The part editor should do something like the following method of the Clock part, which shows the Alarm Settings dialog:
When the user clicks in the close box of the modeless dialog, the part may wish to hide the window rather than close it, so that it is not destroyed and can be redisplayed rapidly.
Parts should hide their palettes and dialogs when deactivated, and also when the process is deactivated . In the Test Clock example, the dialogs are shared between part instances. See also Shared Windows recipe.
When the selection focus is lost or gained, the global object managing the dialogs is notified: